package com.gph.saviorframework.security.web.controller;

import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.gph.saviorframework.Constants;
import com.gph.saviorframework.OaConstants;
import com.gph.saviorframework.SaviorFrameworkException;
import com.gph.saviorframework.common.model.Menu;
import com.gph.saviorframework.security.service.MenuService;
import com.gph.saviorframework.security.web.editor.MenuEditor;
import com.gph.saviorframework.uitl.SecurityUtils;
import com.gph.saviorframework.util.RequestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/" + OaConstants.FRAMEWORK_REQUEST_PATH + "/menu")
public class MenuController {

    /** 日志输出 */
    final Logger logger = LoggerFactory.getLogger(MenuController.class);

    /** 领域对象名称 */
    private final String domain = Menu.class.getSimpleName().toLowerCase();

    /** 视图前缀 */
    private final String viewPrefix = OaConstants.FRAMEWORK_REQUEST_PATH + "/" + OaConstants.MODULE_CATEGORY_SECURITY + "/" + domain + "/" + domain + "_";


    @Autowired
    private MenuService menuService;

    @Autowired
    private SecurityUtils securityUtils;

    @Autowired
    private MessageSourceAccessor messages;

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Menu.class, new MenuEditor(menuService));
    }

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String indexPage() throws SaviorFrameworkException {
        return viewPrefix + "index";
    }

    @RequestMapping(value = "/list", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap list(
            @RequestParam(value = OaConstants.DEFAULT_PAGE_MODEL_KEY, required = false, defaultValue = OaConstants.DEFAULT_PAGE_START) Integer start,
            @RequestParam(value = OaConstants.DEFAULT_RECORD_MODEL_KEY, required = false, defaultValue = OaConstants.DEFAULT_PAGE_SIZE) Integer limit,
            @RequestParam(value = OaConstants.DEFAULT_SORT_MODEL_KEY, required = false, defaultValue = OaConstants.DEFAULT_SORT_FIELD) String sort,
            @RequestParam(value = OaConstants.DEFAULT_DIR_MODEL_KEY, required = false, defaultValue = OaConstants.DEFAULT_SORT_DIRECTION) String dir,
            @RequestParam(value = "parent",required = false)String parent,
            HttpServletRequest request) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        Map<String, Object> params = RequestUtil.getQueryMap(request, menuService.getFields());
        try {
            PageHelper.startPage(start, limit);
            List<Map<String,Object>> list = menuService.find(parent,sort, dir, params);
            PageInfo pageInfo = new PageInfo(list);
            modelMap.addAttribute(OaConstants.DEFAULT_RECORD_MODEL_KEY, list);
            modelMap.addAttribute(OaConstants.DEFAULT_COUNT_MODEL_KEY, menuService.count(parent,params));
            modelMap.addAttribute(OaConstants.DEFAULT_COUNT_MODEL_KEY, pageInfo.getPages());
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            logger.info(messages.getMessage("log.info.list", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain) }));
        }
        catch (DataAccessException e) {
            e.printStackTrace();
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            logger.error(messages.getMessage("log.error.list", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain) }));
        }
        return modelMap;
    }

    /**
     * 返回新建页面
     *
     * @return 新建页面视图名称
     * @throws SaviorFrameworkException
     */
    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public String create() throws SaviorFrameworkException {
        return viewPrefix + "create";
    }

    /**
     * 保存新建数据
     *
     * @param menu 数据对象
     * @return
     * @throws SaviorFrameworkException
     */
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap save(@ModelAttribute Menu menu) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            securityUtils.setCreateEntity(menu);
            menu.setVersion(OaConstants.VERSION_INIT_VALUE);
            menuService.save(menu);
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            modelMap.addAttribute(OaConstants.DEFAULT_ID_KEY, menu.getId());
            logger.info(messages.getMessage("log.info.create",
                    new String[]{securityUtils.getUserFullName(), messages.getMessage(domain), menu.getId()}));
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(OaConstants.DEFAULT_ERROR_KEY, e.getMessage());
            logger.error(messages.getMessage("log.error.create", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain)}));
        }
        return modelMap;
    }

    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public String editPage() throws SaviorFrameworkException {
        return viewPrefix + "edit";
    }

    @RequestMapping(value = "/edit/{id}", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap update(@PathVariable("id") String id, HttpServletRequest request) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            Menu menu = menuService.get(id);
            ServletRequestDataBinder binder = new ServletRequestDataBinder(menu);
            initBinder(binder);
            binder.bind(request);
            securityUtils.setModifyEntity(menu);
            menu.setVersion(menu.getVersion() + 1);
            menuService.update(menu);
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
                    logger.info(messages.getMessage("log.info.edit", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain), id}));
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(OaConstants.DEFAULT_ERROR_KEY, e.getMessage());
            logger.error(messages.getMessage("log.error.edit", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain), id }));
        }
        return modelMap;
    }

    @RequestMapping(value = "/view/{id}", method = RequestMethod.GET)
    @ResponseBody
    public ModelMap get(@PathVariable("id") String id) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            modelMap.addAttribute(OaConstants.DEFAULT_RECORD_MODEL_KEY, menuService.findById(id));
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(OaConstants.DEFAULT_ERROR_KEY, e.getMessage());
        }
        return modelMap;
    }

    @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
    @ResponseBody
    public ModelMap delete(@RequestParam(value = "ids", required = true) String[] ids) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            menuService.deleteByIds(ids);
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            logger.info(messages.getMessage("log.info.delete", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain),
                    StringUtils.arrayToDelimitedString((Object[]) ids, "|")}));
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(OaConstants.DEFAULT_ERROR_KEY, e.getMessage());
            logger.error(messages.getMessage("log.error.delete", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain),
                    StringUtils.arrayToDelimitedString((Object[]) ids, "|")}));
        }
        return modelMap;
    }

    @RequestMapping(value = "/children", method = RequestMethod.GET)
    @ResponseBody
    public void children(HttpServletRequest request,HttpServletResponse response) throws IOException {
        JSONArray array = new JSONArray();
        String id = request.getParameter("id");
        if(org.apache.commons.lang.StringUtils.isEmpty(id)){
            id="TREE_ROOT_NODE";
        }
        List<Map<String, Object>> list = menuService.findByParent(id);
        for(Map<String,Object> map : list){
            map.put("drag",true);
        }
        array = JSONArray.parseArray(JSONArray.toJSONString(list));
        response.getWriter().write(array.toString());
    }

    /**
     * 通过拖拽移动节点
     * @param sourceId
     * @param request
     * @return
     * @throws SaviorFrameworkException
     */
    @RequestMapping(value = "/move", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap move(@RequestParam(value = "sourceId") String sourceId,
                         @RequestParam(value = "targetId") String targetId,
                         HttpServletRequest request) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            Menu sourceMenu = menuService.get(sourceId);
            if(sourceMenu!=null){
                sourceMenu.setParent(menuService.get(targetId));
            }
            menuService.update(sourceMenu);
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            logger.info(messages.getMessage("log.info.edit", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain), sourceId}));
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(OaConstants.DEFAULT_ERROR_KEY, e.getMessage());
            logger.error(messages.getMessage("log.error.edit", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain), sourceId }));
        }
        return modelMap;
    }


    @RequestMapping(value = "/findByParent/{parentId}",method = RequestMethod.GET)
    @ResponseBody
    public String findByParent(@PathVariable(value = "parentId") String parentId, HttpServletRequest request) throws SaviorFrameworkException{
        HashMap res=new HashMap();
        try{
            List<Map<String, Object>> childMenus = menuService.findByParent(parentId, "admin");
            res.put("data",childMenus);
            res.put(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }catch (Exception e){
            e.printStackTrace();
            res.put(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            res.put(Constants.DEFAULT_ERROR_KEY, "服务器内部错误");
        }
        return JSONArray.toJSONString(res);
    }
}
